@This document covers the files associated with the file downlink command and the internship
of Blake A. Harriman

@date August 9, 2019
@author Blake A. Harriman

Files Covered:
-file_decoder.py
-file_writer.py
-file_data.py
-main_frame_factory.py

**(To Do List at bottom)**

At the end of this internship, the work I have done now follows the architecture built by the previous interns
at JPL.  Raw binary data is sent to file_decoder.py where it is decoded into individual packets (START, DATA,
END, CANCEL).  These packets can be sent to any consumers under file_decoder.  In the case of this internship
it would be sending them to file_writer.py to be written to file.  This looks like as follows:

 --------------                      --------------                      --------------
|              |                    |              |                    |              | 
|              |                    |              |                    |              |
|     TCP      |    Binary Data     |     File     |   Decoded Data     |   Consumer   |
|    Server    | ---------------->  |    Decoder   | ---------------->  | (FileWriter) | 
|              |                    |              |                    |              |
|              |                    |              |                    |              |
 --------------                      --------------                      --------------


File Decoder can send the decoded data to multiple consumers to do anything as long as the consumers have been
registered to File Decoder in main_frame_factory.py.  Note that files such as File Decoder should be generic
and not include any code that would be used in a consumer (e.g. don't write to files in File Decoder because
that should be done in a consumer like File Writer).  An example of another possible consumer could be a
progress bar and the decoded data could indicate if the bar can be full to signal completion or if it needs to
be stopped because a timeout was detected.

An important thing to note is that all consumers must have a data_callback function inside them.  When the file
decoder calls send_to_all(), the consumers receive the data via the data_callback function so this must be
included i.e. data_callback(self, data) ----> data = decoded data received

In order for this architecture to work well, File Decoder must also have a place to return the decoded data to.
In this case, the decoded data is returned to file_data.py.  The file has classes for the 4 different packet
types and the specific attributes they contain.  For example, DATA packets have the attributes packetType, seqID,
offset, length, dataVar.  These attributes can be used in the consumers of File Decoder.

**TODO LIST:**
I think I've done a pretty good job writing and commenting this code so not too much work needs to be done.  The
functionality for this decoder and consumer is there so it is mostly done aside from a few things.
file_decoder.py:
    -Possibly look into Cancel packets being needed or deleted.  Not sure if they are
    really required, but it might be something nice to have just in case they ever pop
    up.  Tim seems to want to keep them, but this could still be something to eventually
    look into
file_writer.py:
    -My state machine implementation is kinda messy due to time crunch.  Can possibly
    look into using switch statements and making it more readable
    
    -Currently, even if the downlink times out the program will still read through all
    of the packets.  This means that if we get a lot of packets timing out, then the
    program will take a long time to process everything before the user can do a command
    again.  Is this what we want or do we want to find a way to stop the program from
    continuing to read the packets so the user can act again immediately?  I'm not sure
    if my code actually solves this problem or not so this is definitely worth looking
    into
    
    -I was unable to write unit tests due to the time crunch for this project.  Writing
    unit tests could be helpful for assisting you and others with testing this class
    
    -One problem that we could possibly run into is if we receive less packets than what
    we are supposed to get.  For example, there are 200 packets, but we only receive 180.
    Figuring out a way to print a warning or error to the log file and doing something in
    response to this would be a good idea.
    
    -Currently, the timeout duration is set to 120 seconds.  Maybe something could be added
    to allow the user to easily change what the timeout duration should be?
    
    -The verbose variable decides what is printed to the log file.  Similar to the timeout
    duration variable, maybe something could be added that would allow the user to easily
    change what the verbosity of the program is?
file_data.py:
    -Nothing that I can think of
main_frame_factory.py:
    -None

MISC:
Things that have not been completely tested:
1) Case where multiple START packets are received
2) Case where state is ACTIVE and a START packet has been received
3) Receiving a packet with a certain SeqID when a different SeqID was expected (out of order packets)

Note: The code is written that should deal with all of these cases, but they have not been completely tested